package com.xiebishe.mylibrary.net.retrofit.remoteCallAdapter

import com.xiebishe.mylibrary.net.retrofit.ExceptionHandle
import com.xiebishe.mylibrary.net.retrofit.ExceptionHandler
import net.caiyixiu.liaoji.net.retrofit.remoteCallAdapter.CoroutineCall
import kotlin.coroutines.CoroutineContext

abstract class RemoteCall<T> : CoroutineCall<T, ExceptionHandle.ResponeThrowable, RemoteCall<T>>() {
    private var onResNotFound: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null
    private var onNotLoginError: (() -> Boolean)? = null
    private var onServerMaintenance: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null
    private var onCustomError: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null
    private var onOtherError: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null
    private var onUnknowError: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null
    private var onNetWorkError: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null
    private var onNetDisconnectError: ((responeThrowable: ExceptionHandle.ResponeThrowable) -> Boolean)? = null

    override fun handleThrowable(t: Throwable): ExceptionHandle.ResponeThrowable {
        return ExceptionHandle.handleException(t)
    }

    override fun async(bgContext: CoroutineContext?, handleContext: CoroutineContext?, onException: ((e: ExceptionHandle.ResponeThrowable) -> Unit)?, onSuccess: (data: T) -> Unit) {
        val funcException = { exception: ExceptionHandle.ResponeThrowable ->
            val defaultHandler = object : ExceptionHandler() {
                override fun onFinalError(e: Throwable) {
                    if (e is ExceptionHandle.ResponeThrowable)
                        onException?.invoke(e)
                }

                override fun onResNotFoundError(responeThrowable: ExceptionHandle.ResponeThrowable): Boolean {
                    return onResNotFound?.invoke(responeThrowable)
                            ?: super.onResNotFoundError(responeThrowable)
                }

                override fun onNotLoginError(): Boolean {
                    return onNotLoginError?.invoke() ?: super.onNotLoginError()
                }

                override fun onCustomError(error: ExceptionHandle.ResponeThrowable): Boolean {
                    return onCustomError?.invoke(error) ?: super.onCustomError(error)
                }

                override fun onOtherError(error: ExceptionHandle.ResponeThrowable): Boolean {
                    return onOtherError?.invoke(error) ?: super.onOtherError(error)
                }

                override fun onUnknowError(error: ExceptionHandle.ResponeThrowable): Boolean {
                    return onUnknowError?.invoke(error) ?: super.onUnknowError(error)
                }

                override fun onNetWorkError(e: ExceptionHandle.ResponeThrowable): Boolean {
                    return onNetWorkError?.invoke(e) ?: super.onNetWorkError(e)
                }

                override fun onNetDisconnectError(e: ExceptionHandle.ResponeThrowable): Boolean {
                    return onNetDisconnectError?.invoke(e) ?: super.onNetDisconnectError(e)
                }
            }
            defaultHandler.handleException(exception)
        }
        super.async(bgContext, handleContext, funcException, onSuccess)
    }

    fun onResNotFoundError(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onResNotFound = block
    }

    fun onServerMaintenance(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onServerMaintenance = block
    }

    fun onNotLoginError(block: () -> Boolean) {
        onNotLoginError = block
    }

    fun onCustomError(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onCustomError = block
    }

    fun onOtherError(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onOtherError = block
    }

    fun onUnknownError(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onUnknowError = block
    }

    fun onNetWorkError(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onNetWorkError = block
    }

    fun onNetDisconnectError(block: (responseThrowable: ExceptionHandle.ResponeThrowable) -> Boolean) {
        onNetDisconnectError = block
    }

}